<template>
	<a-modal v-bind="options" class="bill-split-dialog">
		<a-form :model="detail" ref="formRef">
			<vxe-grid ref="grid" :data="detail.billDetailList || []" :loading="loadings.detail" v-bind="gridOptions">
				<template #feeSubjectValue="{row}">
					<span>{{ row.feeSubjectValue }}</span>
				</template>
				<template #spiltStatus="{row}">
					<span>{{ 1 === row.spiltStatus ? '未开票' : '已开票' }}</span>
				</template>
				<template #splitMoney="{row, rowIndex}">
					<!-- 不参与拆分 || 待收付金额为0 || 已开票 -->
					<span v-if="disabledDicList.includes(row.feeSubjectId) || 0 === row.notOccurredMoney || 0 === row.spiltStatus">-</span>
					<a-form-item
						v-else
						:name="['billDetailList', rowIndex, 'splitMoney']"
						:rules="[{required: false, type: 'number'}]"
						has-feedback>
						<template #help />
						<!-- 拆分金额 -->
						<a-input-number
							v-model:value="row.splitMoney"
							:min="0"
							:precision="2"
							placeholder="请输入金额"
							style="width: 100%"
							@blur="e => onblur(e, rowIndex)">
							<template #prefix>
								<span v-color="{color: amountColor(row)}">{{ amountSymbol(row) }}</span>
							</template>
						</a-input-number>
					</a-form-item>
				</template>
				<template #residueMoney="{row}">
					<span v-color="{color: amountColor(row)}">{{ amountSymbol(row) }}</span>
					<span>{{ (row.notOccurredMoney - (row.splitMoney || 0)).toFixed(2) }}</span>
				</template>
				<template #bottom>
					<vxe-toolbar perfect>
						<template #buttons>
							待收(付) 总计
							<span v-color="{color: 'primary'}">&nbsp;{{ notOccurredMoney.toLocaleString() }}</span>
							&nbsp;元 ;本次拆出金额总计
							<span v-color="{color: 'primary'}">&nbsp;{{ splitMoney.toLocaleString() }}</span>
							&nbsp;元 ;账单剩余金额总计
							<span v-color="{color: 'primary'}">&nbsp;{{ (notOccurredMoney - splitMoney).toLocaleString() }}</span>
							&nbsp;元
						</template>
					</vxe-toolbar>
				</template>
			</vxe-grid>

			<a-typography-text strong>
				<blockquote>支付详情 - 新账单</blockquote>
			</a-typography-text>
			<a-row :gutter="24">
				<a-col :span="12">
					<a-form-item label="客户姓名" name="payerName" :rules="[{required: true, message: '请输入客户姓名'}]">
						<a-input disabled placeholder="请输入客户姓名" v-model:value="detail.payerName" />
					</a-form-item>
				</a-col>
				<a-col :span="12">
					<a-form-item
						label="客户电话"
						name="payerPhone"
						:rules="[{required: true, validator: 2 === contractType ? validateTel : validatePhone}]">
						<a-input
							disabled
							placeholder="请输入客户电话"
							v-model:value="detail.payerPhone"
							:maxlength="2 === contractType ? 13 : 11" />
					</a-form-item>
				</a-col>
				<a-col :span="12">
					<a-form-item name="predictTime" label="支付时间" :rules="[{required: true, message: '请选择支付时间'}]">
						<a-date-picker v-model:value="detail.predictTime" :value-format="DATE_FORMAT.DATETIME" />
					</a-form-item>
				</a-col>
				<a-col :span="12">
					<a-form-item name="billCycle" label="账单周期" :rules="[{required: true, message: '请选择账单周期'}]">
						<a-range-picker disabled v-model:value="detail.billCycle" :value-format="DATE_FORMAT.DATE" />
					</a-form-item>
				</a-col>
			</a-row>
			<a-form-item label="账单备注" name="comment">
				<a-textarea v-model:value="detail.comment" show-count :maxlength="200" placeholder="请输入账单备注" />
			</a-form-item>
			<a-form-item label="账单凭证">
				<file-upload ref="fileRef" v-model:files="files" show-qr-code show-tips />
			</a-form-item>
		</a-form>
		<template #footer>
			<a-space :size="12">
				<a-button :loading="loadings.submit" @click="options.onCancel">取消</a-button>
				<a-button :loading="loadings.submit" type="primary" @click="options.onOk">确定</a-button>
			</a-space>
		</template>
	</a-modal>
</template>

<script lang="ts" setup>
	import {reactive, ref, toRef, watch, computed} from 'vue'
	import {Img} from 'yuxin-base/src/types'
	import {BillDeatil, splitBillType} from '@/interface/bill'
	import {VxeGridInstance, VxeGridProps} from 'vxe-table'
	import settingApi from 'yuxin-base/src/api/setting-api'
	import {DIC_LABEL_MAP} from 'yuxin-base/src/constant'
	import {getFinanceByBillId, billSplit} from '@/api/bill'
	import {amountColor, amountSymbol} from 'yuxin-base/src/utils'
	import DATE_FORMAT from 'yuxin-base/src/utils/date'
	import {validatePhone, validateTel} from '@/utils/formValidation'
	import {message, FormInstance} from 'ant-design-vue'
	import XEUtils from 'xe-utils'
	import Snowflake from 'vue-snowflake'

	const props = defineProps<{
		// 账单id
		id?: string
		visible: boolean
	}>()
	/** 当前选中的合同类型 1 个人 2 企业 */
	const contractType = ref<number | null>(1)
	const emits = defineEmits(['update:visible', 'close'])
	const files = ref<Img[]>([])
	const costTypes = ref<any[]>([])
	const grid = ref<VxeGridInstance>()
	const formRef = ref<FormInstance>()

	const detail = ref<BillDeatil>({
		billDetailList: []
	})
	const loadings = reactive({
		detail: false,
		submit: false
	})
	const options = reactive({
		width: 1200,
		title: '账单拆分',
		centered: true,
		maskClosable: false,
		destroyOnClose: true,
		visible: toRef(props, 'visible'),
		onCancel() {
			files.value = []
			emits('update:visible', false)
			setTimeout(() => emits('close'), 100)
		},
		onOk() {
			submit()
		}
	})

	// 计算拆分金额
	const splitMoney = computed(() => {
		const list = detail.value.billDetailList || []
		const total = list.reduce(
			(prev, cur) => {
				prev.splitMoney += (cur.splitMoney || 0) * (cur.feeDirection === 1 ? 1 : -1)
				return prev
			},
			{splitMoney: 0}
		)
		return Number(total.splitMoney.toFixed(2))
	})

	// 计算待收付金额
	const notOccurredMoney = computed(() => {
		const list = detail.value.billDetailList || []
		const total = list.reduce(
			(prev, cur) => {
				prev.notOccurredMoney += cur.notOccurredMoney * (cur.feeDirection === 1 ? 1 : -1)
				return prev
			},
			{notOccurredMoney: 0}
		)
		return Number(total.notOccurredMoney.toFixed(2))
	})

	const gridOptions = reactive<VxeGridProps>({
		size: 'small',
		height: 300,
		showOverflow: true,
		rowConfig: {
			isHover: true
		},
		columns: [
			{
				title: '费用科目',
				minWidth: 200,
				slots: {
					default: 'feeSubjectValue'
				}
			},
			{
				title: '开票状态',
				minWidth: 100,
				slots: {
					default: 'spiltStatus'
				}
			},
			{
				title: '应收(付)',
				minWidth: 100,
				field: 'originalMoney'
			},
			{
				title: '已收(付)',
				field: 'occurredMoney',
				minWidth: 100
			},
			{
				title: '待收(付)',
				field: 'notOccurredMoney',
				minWidth: 100
			},
			{
				title: '本项拆出金额',
				slots: {
					default: 'splitMoney'
				},
				minWidth: 200
			},
			{
				title: '本项剩余金额',
				slots: {
					default: 'residueMoney'
				},
				minWidth: 200
			}
		]
	})

	// 押金、定金、押金结转不参与拆分
	const disabledDicList = computed(() => {
		// 不允许拆分的押金大类labels [定金，押金，押金结转]
		const disabledFatherArr = ['FEESUBJECT@EARNEST', 'FEESUBJECT@DEPOSIT']
		const sonArr: Array<string> = costTypes.value.reduce((prev, curr) => {
			if (disabledFatherArr.includes(curr.label)) {
				return [...prev, ...curr.metaList.map(i => i.id)]
			}
			return prev
		}, [])
		return sonArr
	})

	// 详情
	const getDetailById = (id: string) => {
		settingApi.getDicListByLabel(DIC_LABEL_MAP['FEESUBJECT']).then(({data}) => {
			costTypes.value = data
		})
		loadings.detail = true
		getFinanceByBillId(id)
			.then(({data}) => {
				detail.value = data
				detail.value.billCycle = [data.beginTime, data.endTime]
				detail.value.billDetailList = detail.value.billDetailList?.map(i => {
					return {
						...i,
						splitMoney: null // 拆分出来的金额 需要靠这个计算拆分金额
					}
				})
				contractType.value = data?.enterContractId ? 2 : 1
			})
			.finally(() => (loadings.detail = false))
	}

	const onblur = (e: any, index: any) => {
		let value = e.target.value

		if (detail.value.billDetailList) {
			let data = detail.value.billDetailList[index]
			if (data.notOccurredMoney < data.splitMoney || 0 === value) {
				data.splitMoney = data.notOccurredMoney
				message.warning('拆分金额不可高于待收（付）金额' + data.notOccurredMoney + '元')
			}
		}
	}

	const createSplitBill = () => {
		const billList = XEUtils.clone(detail.value.billDetailList || [])

		// 生成拆分后的新收支集合(就是将你拆分出来的金额作为原始金额)
		const billDetailFormAddList: Array<splitBillType> = billList
			.filter(i => Boolean(i.splitMoney))
			.map(i => {
				return {
					isOccur: 0, // 0 预计发生 1 实际发生
					feeSubjectId: i.feeSubjectId,
					feeSubjectValue: i.feeSubjectValue,
					feeDirection: i.feeDirection, //费用方向
					notOccurredMoney: i.splitMoney, //未发生金额
					occurredMoney: 0, // 已发生金额
					originalMoney: i.splitMoney, // 原始金额
					spiltDetailId: i.id
				}
			})
		// 	拆分需修改的收支集合(有拆分金额的话需要减去拆分金额的钱)
		const billDetailFormList: Array<any> = billList
			.filter(i => i.splitMoney)
			.map(i => {
				return {
					id: i.id,
					isOccur: i.isOccur,
					feeSubjectId: i.feeSubjectId,
					feeSubjectValue: i.feeSubjectValue,
					feeDirection: i.feeDirection,
					originalMoney: Number((i.originalMoney - i.splitMoney).toFixed(2)), // 处理精度问题
					notOccurredMoney: Number((i.notOccurredMoney - i.splitMoney).toFixed(2)), // 处理精度问题
					occurredMoney: i.occurredMoney
				}
			})

		return {
			billDetailFormAddList,
			billDetailFormList
		}
	}

	const submit = () => {
		// 检验必须填写一项且不为0(过滤掉不参与拆分 + 有值的)
		const checkArr: Array<any> = (detail.value.billDetailList || [])
			.filter(i => !disabledDicList.value.includes(i.feeSubjectId))
			.filter(i => Boolean(i.splitMoney))
		if (checkArr.length > 0) {
			formRef.value
				?.validate()
				.then(async () => {
					const {billDetailFormAddList, billDetailFormList} = createSplitBill()

					const rawValue = detail.value
					const node = new Snowflake.init(1, 1, 0)
					const params = {
						billIdNew: node.createID(), // 需要生成默认的bizId绑定图片
						billId: rawValue.id,
						predictTime: rawValue.predictTime,
						attachments: files.value.map(o => o.id).join(),
						comment: rawValue.comment,
						billDetailFormAddList,
						billDetailFormList
					}

					loadings.submit = true
					billSplit(params)
						.then(res => {
							message.success('操作成功')
							options.onCancel()
						})
						.finally(() => {
							loadings.submit = false
						})
				})
				.catch(() => {
					console.log('Form verification failed')
				})
		} else {
			message.error('请至少填写一项拆分金额，且不等于0')
		}
	}

	watch(
		() => [props.visible, props.id],
		() => {
			if (props.visible && props.id) {
				getDetailById(props.id)
			}
		}
	)
</script>

<style lang="less">
	.bill-split-dialog {
		.ant-modal-body {
			overflow: auto;
			min-height: 600px;
			max-height: 900px;
			padding: 16px 16px 0;

			.ant-form-item-label {
				width: 120px;
			}
		}
	}
</style>
